/**
 * 简化加密数据库配置模块
 * EndoSight-UC 医疗AI系统 - 焦土协议 Phase 3
 *
 * 使用AES-256-CBC实现应用级数据库加密
 */

import sqlite3 from 'sqlite3';
import crypto from 'crypto';
import path from 'path';
import { fileURLToPath } from 'url';
import { createSecureLogger } from '../utils/secureLoggingConfig.js';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// 安全日志记录器
const logger = createSecureLogger({
  service: 'SimpleEncryptedDB',
  logLevel: process.env.LOG_LEVEL || 'info'
});

// 加密配置 - 使用AES-256-CBC
const encryptionConfig = {
  algorithm: 'aes-256-cbc',
  keyLength: 32, // 256 bits
  ivLength: 16   // 128 bits
};

// 从环境变量获取加密密钥
const getEncryptionKey = () => {
  const key = process.env.DB_ENCRYPTION_KEY;
  if (!key) {
    throw new Error('DB_ENCRYPTION_KEY environment variable is required for database encryption');
  }
  return Buffer.from(key, 'hex').slice(0, encryptionConfig.keyLength);
};

/**
 * 加密数据
 * @param {string} text - 要加密的文本
 * @param {Buffer} key - 加密密钥
 * @returns {Object} 加密结果 {encrypted, iv}
 */
const encrypt = (text, key) => {
  try {
    const iv = crypto.randomBytes(encryptionConfig.ivLength);
    const cipher = crypto.createCipher(encryptionConfig.algorithm, key);

    let encrypted = cipher.update(text, 'utf8', 'hex');
    encrypted += cipher.final('hex');

    logger.debug('数据加密成功', {
      length: text.length,
      encryptedLength: encrypted.length
    });

    return {
      encrypted,
      iv: iv.toString('hex')
    };
  } catch (error) {
    logger.logError(error, { operation: 'encrypt_data' });
    throw error;
  }
};

/**
 * 解密数据
 * @param {Object} encryptedData - 加密数据对象
 * @param {Buffer} key - 解密密钥
 * @returns {string} 解密后的文本
 */
const decrypt = (encryptedData, key) => {
  try {
    const decipher = crypto.createDecipher(encryptionConfig.algorithm, key);
    decipher.setAAD(Buffer.from(encryptedData.iv, 'hex'));

    let decrypted = decipher.update(encryptedData.encrypted, 'hex', 'utf8');
    decrypted += decipher.final('utf8');

    logger.debug('数据解密成功', {
      decryptedLength: decrypted.length
    });

    return decrypted;
  } catch (error) {
    logger.logError(error, { operation: 'decrypt_data' });
    throw new Error('数据解密失败: 可能的密钥错误或数据损坏');
  }
};

/**
 * 创建简单加密数据库包装器
 */
class SimpleEncryptedDatabase {
  constructor(dbPath, encryptionKey) {
    this.dbPath = dbPath;
    this.encryptionKey = encryptionKey;
    this.db = null;

    // 定义需要加密的敏感字段
    this.sensitiveFields = {
      doctors: ['password', 'email', 'license_number'],
      patients: ['name', 'id_card', 'phone', 'email', 'address'],
      scoring_records: ['doctor_notes', 'patient_complaints']
    };
  }

  /**
   * 初始化数据库连接
   */
  async initialize() {
    return new Promise((resolve, reject) => {
      logger.info('初始化简化加密数据库连接', {
        dbPath: this.dbPath,
        algorithm: encryptionConfig.algorithm
      });

      this.db = new sqlite3.Database(this.dbPath, (err) => {
        if (err) {
          logger.logError(err, { operation: 'database_connection' });
          return reject(err);
        }

        logger.info('简化加密数据库连接成功');

        // 启用外键约束
        this.db.run('PRAGMA foreign_keys = ON');

        // 设置WAL模式以提高性能
        this.db.run('PRAGMA journal_mode = WAL');

        resolve();
      });
    });
  }

  /**
   * 执行加密的查询
   */
  async run(sql, params = [], options = {}) {
    return new Promise((resolve, reject) => {
      const { encryptFields = [], table = null } = options;

      let processedParams = params;

      // 如果指定了加密字段，加密相关参数
      if (encryptFields.length > 0 && table && this.sensitiveFields[table]) {
        const fieldsToEncrypt = this.sensitiveFields[table].filter(
          field => encryptFields.includes(field)
        );

        if (fieldsToEncrypt.length > 0) {
          processedParams = params.map((param, index) => {
            if (typeof param === 'string' && encryptFields[index]) {
              const encrypted = encrypt(param, this.encryptionKey);
              return JSON.stringify(encrypted);
            }
            return param;
          });
        }
      }

      this.db.run(sql, processedParams, function(err) {
        if (err) {
          logger.logError(err, {
            operation: 'database_run',
            sql: sql.substring(0, 100) + '...'
          });
          return reject(err);
        }

        resolve({
          id: this.lastID,
          changes: this.changes
        });
      });
    });
  }

  /**
   * 执行查询并返回结果
   */
  async get(sql, params = [], options = {}) {
    return new Promise((resolve, reject) => {
      const { decryptFields = [], table = null } = options;

      this.db.get(sql, params, (err, row) => {
        if (err) {
          logger.logError(err, {
            operation: 'database_get',
            sql: sql.substring(0, 100) + '...'
          });
          return reject(err);
        }

        // 如果指定了解密字段，解密相关数据
        if (row && decryptFields.length > 0 && table && this.sensitiveFields[table]) {
          try {
            row = decryptSensitiveFields(row, decryptFields, this.encryptionKey);
          } catch (decryptError) {
            logger.warn('查询结果解密失败', {
              table,
              error: decryptError.message
            });
          }
        }

        resolve(row);
      });
    });
  }

  /**
   * 执行查询并返回所有结果
   */
  async all(sql, params = [], options = {}) {
    return new Promise((resolve, reject) => {
      const { decryptFields = [], table = null } = options;

      this.db.all(sql, params, (err, rows) => {
        if (err) {
          logger.logError(err, {
            operation: 'database_all',
            sql: sql.substring(0, 100) + '...'
          });
          return reject(err);
        }

        // 如果指定了解密字段，解密所有结果
        if (rows && decryptFields.length > 0 && table && this.sensitiveFields[table]) {
          try {
            rows = rows.map(row =>
              decryptSensitiveFields(row, decryptFields, this.encryptionKey)
            );
          } catch (decryptError) {
            logger.warn('查询结果解密失败', {
              table,
              error: decryptError.message
            });
          }
        }

        resolve(rows);
      });
    });
  }

  /**
   * 关闭数据库连接
   */
  async close() {
    return new Promise((resolve, reject) => {
      if (this.db) {
        this.db.close((err) => {
          if (err) {
            logger.logError(err, { operation: 'database_close' });
            return reject(err);
          }

          logger.info('简化加密数据库连接已关闭');
          resolve();
        });
      } else {
        resolve();
      }
    });
  }

  /**
   * 测试加密功能
   */
  async testEncryption() {
    try {
      const testData = '敏感测试数据';
      const encrypted = encrypt(testData, this.encryptionKey);
      const decrypted = decrypt(encrypted, this.encryptionKey);

      const success = testData === decrypted;

      logger.info('简化加密功能测试', {
        success,
        originalLength: testData.length,
        encryptedLength: encrypted.encrypted.length
      });

      return success;
    } catch (error) {
      logger.logError(error, { operation: 'encryption_test' });
      return false;
    }
  }
}

/**
 * 解密敏感字段
 */
const decryptSensitiveFields = (data, sensitiveFields, key) => {
  const decryptedData = { ...data };

  for (const field of sensitiveFields) {
    const encryptedField = `${field}_encrypted`;
    if (decryptedData[encryptedField]) {
      try {
        const encryptedData = JSON.parse(decryptedData[encryptedField]);
        decryptedData[field] = decrypt(encryptedData, key);
        delete decryptedData[encryptedField];
      } catch (error) {
        logger.warn('字段解密失败', {
          field,
          error: error.message
        });
      }
    }
  }

  return decryptedData;
};

/**
 * 创建简化加密数据库实例
 */
export const createSimpleEncryptedDatabase = async (dbPath) => {
  try {
    const encryptionKey = getEncryptionKey();
    const encryptedDb = new SimpleEncryptedDatabase(dbPath, encryptionKey);

    await encryptedDb.initialize();

    // 测试加密功能
    const testResult = await encryptedDb.testEncryption();
    if (!testResult) {
      throw new Error('简化数据库加密功能测试失败');
    }

    logger.info('简化加密数据库初始化完成', {
      algorithm: encryptionConfig.algorithm,
      keyLength: encryptionConfig.keyLength * 8,
      dbPath
    });

    return encryptedDb;
  } catch (error) {
    logger.logError(error, { operation: 'create_simple_encrypted_database' });
    throw error;
  }
};

export default {
  createSimpleEncryptedDatabase,
  encrypt,
  decrypt,
  encryptionConfig
};